/*
 * Copyright 2013 Sigurd Randoll.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package de.digiway.rapidbreeze.client.infrastructure;

import de.digiway.rapidbreeze.client.config.ClientConfiguration;
import de.digiway.rapidbreeze.client.model.info.ServerInformationResourceService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.rribbit.RRB;
import org.rribbit.RequestResponseBus;

/**
 * A watchdog which monitors in a configured interval the connection state to
 * the server. It fires a bus event on a connection change.
 *
 * @author Sigurd
 */
public class ConnectionWatchdog {

    RequestResponseBus rrb;
    private ServerInformationResourceService informationResourceService;
    private ClientConfiguration configuration;
    private ScheduledFuture<?> watchdogFuture;
    private ScheduledExecutorService executorService;
    private static final Logger LOG = Logger.getLogger(ConnectionWatchdog.class.getName());

    public ConnectionWatchdog(ClientConfiguration clientConfiguration, ServerInformationResourceService informationResourceService) {
        this.informationResourceService = informationResourceService;
        this.configuration = clientConfiguration;
        this.rrb = RRB.get();
        this.executorService = ThreadPoolService.getScheduledPool();
    }

    /**
     * Starts the watchdog
     */
    public void start() {
        if (watchdogFuture == null) {
            watchdogFuture = executorService.scheduleAtFixedRate(new WatchdogTask(), 1000, configuration.getServerPollingInterval(), TimeUnit.MILLISECONDS);
        }
    }

    /**
     * Stops the watchdog
     */
    public void stop() {
        if (watchdogFuture != null) {
            watchdogFuture.cancel(false);
            watchdogFuture = null;
        }
    }

    private class WatchdogTask implements Runnable {

        private boolean lastState = false;

        @Override
        public void run() {
            try {
                boolean currentState = informationResourceService.isServerAccessible();
                if (lastState != currentState) {
                    fireEvent(currentState);
                    lastState = currentState;
                }
            } catch (RuntimeException ex) {
                LOG.log(Level.SEVERE, "An exception occured during watchdog execution.", ex);
            }
        }

        private void fireEvent(boolean currentState) {
            rrb.send(BusEvents.SERVER_CONNECTION_CHANGED_EVENT, currentState);
        }
    }
}
